Does the S&P 500 show seasonal patterns?¶

In [10]:
import yfinance as yf
import pandas as pd
import plotly.express as px
In [11]:
# get data from yahoo
data = yf.download("^GSPC", start="2000-01-01")["Close"]
[*********************100%***********************]  1 of 1 completed
In [12]:
# calculate the returns
returns = data.pct_change()
In [13]:
# resample the data
monthly = returns.resample("M").sum()
toHeatMap = pd.DataFrame(monthly)
toHeatMap["Month"] = toHeatMap.index.month
toHeatMap["Year"] = toHeatMap.index.year
Show = toHeatMap.groupby(by=['Month', 'Year']).sum().unstack()
Show.columns = Show.columns.droplevel(0)
Show.rename(columns={1: "January", 2: "February", 3: "March", 4: "April", 5: "May", 6: "June",
                     7: "July", 8: "August", 9: "September", 10: "October", 11: "November", 12: "December"},
            inplace=True)
Show
Out[13]:
Year 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 ... 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023
Month
1 -0.040071 0.036490 -0.014597 -0.025215 0.017618 -0.025204 0.025636 0.014186 -0.060682 -0.083516 ... -0.035576 -0.030419 -0.049910 0.017894 0.055043 0.077238 -0.001067 -0.010154 -0.052626 0.061058
2 -0.018799 -0.095559 -0.019697 -0.015870 0.012439 0.019144 0.000777 -0.021336 -0.033750 -0.111410 ... 0.042842 0.053843 -0.002836 0.036635 -0.037006 0.029561 -0.085420 0.026509 -0.030017 -0.025587
3 0.095617 -0.062748 0.037082 0.011383 -0.015502 -0.018873 0.011306 0.010725 -0.002841 0.091981 ... 0.007342 -0.016688 0.064536 -0.000102 -0.025627 0.018320 -0.096594 0.042792 0.037517 0.035895
4 -0.027265 0.077682 -0.062222 0.079447 -0.016316 -0.019401 0.012377 0.042669 0.047885 0.093545 ... 0.006866 0.008772 0.003105 0.009245 0.003901 0.038747 0.126466 0.051625 -0.089576 0.015049
5 -0.019572 0.006339 -0.007088 0.050759 0.012500 0.029941 -0.030726 0.032379 0.011440 0.054890 ... 0.021090 0.010879 0.015705 0.011763 0.021838 -0.067118 0.046318 0.006221 0.003959 0.003162
6 0.024826 -0.024598 -0.073355 0.012255 0.018214 0.000128 0.001133 -0.017239 -0.088151 0.001938 ... 0.019020 -0.020707 0.002356 0.005026 0.005143 0.067186 0.021895 0.022274 -0.084018 0.053843
7 -0.015439 -0.009346 -0.074681 0.017114 -0.034502 0.035661 0.005795 -0.031284 -0.007675 0.073399 ... -0.014717 0.020130 0.035228 0.019293 0.035714 0.013340 0.054438 0.023055 0.088779 NaN
8 0.059445 -0.065140 0.009561 0.018200 0.003007 -0.010937 0.021282 0.015356 0.013834 0.034099 ... 0.037236 -0.061689 -0.001081 0.000924 0.030050 -0.016077 0.068089 0.028881 -0.041682 NaN
9 -0.054167 -0.081635 -0.112830 -0.011081 0.009674 0.007254 0.024528 0.036095 -0.083026 0.036056 ... -0.015274 -0.024764 -0.000394 0.019247 0.004400 0.017337 -0.037543 -0.048037 -0.095551 NaN
10 -0.002192 0.019561 0.088637 0.054204 0.014531 -0.016992 0.031246 0.015558 -0.156878 -0.018002 ... 0.024408 0.080522 -0.019434 0.022054 -0.069620 0.020982 -0.026211 0.067431 0.080061 NaN
11 -0.081811 0.073572 0.057716 0.007561 0.038295 0.034851 0.016628 -0.042219 -0.059622 0.056775 ... 0.024312 0.001063 0.034073 0.027873 0.019118 0.033633 0.103382 -0.007700 0.055473 NaN
12 0.006685 0.008443 -0.060907 0.049964 0.032305 -0.000737 0.012715 -0.007488 0.018008 0.018081 ... -0.003205 -0.016265 0.018299 0.009905 -0.092875 0.028440 0.036787 0.043941 -0.059425 NaN

12 rows × 24 columns

In [14]:
# plot the data
import plotly.express as px

fig = px.line(Show)
fig.update_layout(xaxis_title="Month", yaxis_title="Returns",height=700,width=1000)
fig.show()

the analysis reveals a lack of seasonality and a low correlation between the 8th and 10th months of each year.